/******************************************************************************
 * @file     bsp_aht21_driver.c
 * @brief    提供AHT21的hal接口
 * @author   Ruilst
 * @date     2025-08-14
 * @version  V1.0.0
 * @copyright Copyright (c) 2025
 *
 * @note     1 tab = 4 space
 *           include:
 *           bsp_aht21_driver.h
 * @par 日志:
 * - V1.0.0 2025-08-14 Ruilst
 *****************************************************************************/

//******************************** Includes *********************************//

#include "bsp_aht21_driver.h"

//******************************** Includes *********************************//

//******************************** Defines **********************************//

#define AHT21_MEASURE_WAIT_TIME 80    // 每次测量间隔时间-ms
#define AHT21_NOT_TNIT          0     // AHT21未初始化
#define AHT21_INITED            1     // AHT21已初始化
#define AHT21_STATE             0x18  // AHT21的状态字节

#define CRC8_POLYNOMIAL         0x31  // CRC多项式
#define CRC8_INIT               0xFF  // CRC初始值

//******************************** Defines **********************************//

//*********************Thread_Func **********************//

//*********************Thread_Func **********************//

//*********************Queue_Handler ********************//

//*********************Queue_Handler ********************//

//******************************** Declaring ********************************//

/**
 * @brief   CRC8数据校验函数
 *
 * @param   uint8_t *pdata  要校验的数据地址
 * @param   uint8_t length  要校验的数据长度
 * @param   uint8_t *p_crc  校验完的数据缓存地址
 *
 * @return  aht21_status_t 函数运行状态
 *
 * @retval  AHT21_OK               操作成功
 * @retval  AHT21_ERRORPARAMETER   传入参数错误
 */
static aht21_status_t CRC8_check( uint8_t *p_data,
                                  uint8_t  length,
                                  uint8_t *p_crc )
{
    if ( NULL == p_data || NULL == p_crc )
    {
#ifdef DEBUG
        DEBUG_OUT( "CRC8_check parameter p_data is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORPARAMETER;
    }

    uint8_t crc = CRC8_INIT;

    for ( uint8_t i = 0; i < length; i++ )
    {
        crc ^= p_data[i];
        for ( uint8_t j = 0; j < 8; j++ )
        {
            if ( crc & 0x80 )
            {
                crc = ( crc << 1 ) ^ CRC8_POLYNOMIAL;
            }
            else
            {
                crc <<= 1;
            }
        }
    }
    *p_crc = crc;

    return AHT21_OK;
}

/**
 * @brief   aht21读取设备的状态字节
 *
 * @param   bsp_aht21_driver_t *const p_aht21_instance aht21实例结构体指针
 *
 * @return  aht21_status_t 函数运行状态
 *
 * @retval  AHT21_OK               操作成功
 * @retval  AHT21_ERRORPARAMETER   传入参数错误
 * @retval  AHT21_ERRORRESOURCE    IIC资源错误
 */
static aht21_status_t aht21_read_id(
    bsp_aht21_driver_t *const p_aht21_instance )
{
    if ( NULL == p_aht21_instance )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_read_state parameter p_data is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORPARAMETER;
    }

    uint8_t rec_data = 0;

#ifndef HARDWARE_IIC  // 使用软件IIC

#ifdef OS_SUPPORTING
    p_aht21_instance->p_iic_driver_instance->pf_critical_enter();
#endif  // OS_SUPPORTING

    p_aht21_instance->p_iic_driver_instance->pf_iic_start();
    p_aht21_instance->p_iic_driver_instance->pf_iic_send_byte( AHT21_R_ADDRESS,
                                                               NULL );
    if ( AHT21_OK !=
         p_aht21_instance->p_iic_driver_instance->pf_iic_wait_ack() )
    {
        p_aht21_instance->p_iic_driver_instance->pf_iic_stop();
#ifdef DEBUG
        DEBUG_OUT( "aht21_read_state pf_iic_wait_ack is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORRESOURCE;
    }
    p_aht21_instance->p_iic_driver_instance->pf_iic_rec_byte( NULL,
                                                              &rec_data );
    p_aht21_instance->p_iic_driver_instance->pf_iic_stop();

#ifdef OS_SUPPORTING
    p_aht21_instance->p_iic_driver_instance->pf_critical_exit();
#endif  // OS_SUPPORTING

    // 重置AHT21状态寄存器
    if ( 0x18 != 0x18 & rec_data )
    {
        uint8_t init_cmd[] = { 0xBE, 0x08, 0x00 };

#ifdef OS_SUPPORTING
        p_aht21_instance->p_iic_driver_instance->pf_critical_enter();
#endif  // OS_SUPPORTING

        p_aht21_instance->p_iic_driver_instance->pf_iic_start();
        p_aht21_instance->p_iic_driver_instance->pf_iic_send_byte( AHT21_R_ADDRESS, NULL );

        if ( AHT21_OK !=
             p_aht21_instance->p_iic_driver_instance->pf_iic_wait_ack() )
        {
            p_aht21_instance->p_iic_driver_instance->pf_iic_stop();
#ifdef DEBUG
            DEBUG_OUT( "aht21_read_state pf_iic_wait_ack is error\r\n" );
#endif  // DEBUG
            return AHT21_ERRORRESOURCE;
        }

        for ( uint8_t i = 0; i < 3; i++ )
        {
            p_aht21_instance->p_iic_driver_instance->pf_iic_send_byte( NULL, init_cmd[i] );
            if ( AHT21_OK !=
                 p_aht21_instance->p_iic_driver_instance->pf_iic_wait_ack() )
            {
                p_aht21_instance->p_iic_driver_instance->pf_iic_stop();
#ifdef DEBUG
                DEBUG_OUT( "aht21_read_state pf_iic_wait_ack is error\r\n" );
#endif  // DEBUG
                return AHT21_ERRORRESOURCE;
            }
        }
        p_aht21_instance->p_iic_driver_instance->pf_iic_stop();

#ifdef OS_SUPPORTING
        p_aht21_instance->p_iic_driver_instance->pf_critical_enter();
#endif  // OS_SUPPORTING
    }

#endif  // HARDWARE_IIC

    return AHT21_OK;
}

/**
 * @brief   aht21实例初始化函数
 *
 * @param   bsp_aht21_driver_t *const p_aht21_instance  aht21实例结构体指针
 *
 * @return  aht21_status_t 函数运行状态
 *
 * @retval  AHT21_OK               操作成功
 * @retval  AHT21_ERRORPARAMETER   传入参数错误
 * @retval  AHT21_ERRORRESOURCE    未初始化
 */
aht21_status_t aht21_init( bsp_aht21_driver_t *const p_aht21_instance )
{

    p_aht21_instance->p_os_yield_instance->os_yield( 300 );

    if ( NULL == p_aht21_instance->p_iic_driver_instance ||
         NULL == p_aht21_instance->p_iic_driver_instance->pf_critical_enter )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_init input parameter is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORPARAMETER;
    }

#ifndef HAEDWARE_IIC
    p_aht21_instance->p_iic_driver_instance->pf_critical_enter();
#endif  // !HAEDWARE_IIC

    p_aht21_instance->p_iic_driver_instance->pf_iic_init();

    if ( AHT21_OK != aht21_read_id( p_aht21_instance ) )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_init input parameter is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORRESOURCE;
    }

#ifndef HAEDWARE_IIC
    p_aht21_instance->p_iic_driver_instance->pf_critical_exit();
#endif  // !HAEDWARE_IIC

    // 把led实例的初始化状态置为已初始化
    p_aht21_instance->init_state = AHT21_INITED;
#ifdef DEBUG
    DEBUG_OUT( "aht21_init init successfully\r\n" );
#endif  // DEBUG

    return AHT21_OK;
}

/**
 * @brief   aht21实例去初始化函数
 *
 * @param   bsp_aht21_driver_t *const p_aht21_instance  aht21实例结构体指针
 *
 * @return  aht21_status_t 函数运行状态
 *
 * @retval  AHT21_OK               操作成功
 * @retval  AHT21_ERRORPARAMETER   传入参数错误
 */
aht21_status_t aht21_deinit( bsp_aht21_driver_t *const p_aht21_instance )
{
    if ( NULL == p_aht21_instance )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_deinit input parameter is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORPARAMETER;
    }
    p_aht21_instance->init_state = AHT21_NOT_TNIT;

    return AHT21_OK;
}

/**
 * @brief   aht21读温湿度函数
 *
 * @param   bsp_aht21_driver_t *const p_aht21_instance  aht21实例结构体指针
 *
 * @return  aht21_status_t 函数运行状态
 *
 * @retval  AHT21_OK               操作成功
 * @retval  AHT21_ERRORPARAMETER   传入参数错误
 */
aht21_status_t aht21_read_t_h(
    bsp_aht21_driver_t *const p_aht21_instance,
    float *const              temp,
    float *const              humi )
{
    if ( AHT21_NOT_TNIT == p_aht21_instance->init_state )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_read_t_h instance is not init\r\n" );
#endif  // DEBUG
        return AHT21_ERRORRESOURCE;
    }
    uint8_t buffer[7] = { 0 };
}
/**
 * @brief   aht21实例挂载函数接口函数
 *
 * @param   bsp_aht21_driver_t *const p_self_instance            aht21实例结构体指针
 * @param   iic_driver_interface_t *const p_iic_driver_instance  IIC驱动函数指针
 * @param   time_base_interface_t *const  p_time_base_instance   时基函数指针
 * @param   os_yield_interface_t *const p_os_yield_instance      OS延时函数指针
 *
 * @return  aht21_status_t 函数运行状态
 *
 * @retval  AHT21_OK               操作成功
 * @retval  AHT21_ERRORPARAMETER   传入参数错误
 * @retval  AHT21_ERRORRESOURCE    实例未初始化
 */
aht21_status_t aht21_instance_inst(
    bsp_aht21_driver_t *const p_self_instance,
    // 指向当前BSP AHT21驱动实例自身的指针
    iic_driver_interface_t *const p_iic_driver_instance,  // 用于绑定IIC通信功能
#ifndef HARDWARE_IIC
    time_base_interface_t *const p_time_base_instance,  // 用于绑定时间相关功能
#endif                                                  // HARDWARE_IIC
#ifdef OS_SUPPORTING
    os_yield_interface_t *const p_os_yield_instance  // 用于绑定任务调度功能
#endif                                               // OS_SUPPORTING
)
{
    if ( NULL == p_self_instance ||
         NULL == p_iic_driver_instance ||
         NULL == p_time_base_instance ||
         NULL == p_os_yield_instance )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_instance_inst input parameter is error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORPARAMETER;
    }

    if ( AHT21_INITED == p_self_instance->init_state )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_instance_inst instance is inited\r\n" );
#endif  // DEBUG
        return AHT21_ERRORRESOURCE;
    }

    // 挂载实例函数接口
    p_self_instance->p_iic_driver_instance = p_iic_driver_instance;
    p_self_instance->p_time_base_instance  = p_time_base_instance;
    p_self_instance->p_os_yield_instance   = p_os_yield_instance;

    // TBD

    p_self_instance->pf_aht21_instance_init =
        (aht21_status_t( * )( void *const ))aht21_init;
    p_self_instance->pf_aht21_instance_deinit =
        (aht21_status_t( * )( void *const ))aht21_deinit;
    p_self_instance->pf_read_aht21_id =
        (aht21_status_t( * )( void *const ))aht21_read_id;
    p_self_instance->pf_read_aht21_t_h = ;
    p_self_instance->pf_aht21_sleep    = ;
    p_self_instance->pf_aht21_wakeup   = ;

    // TBD
    if ( AHT21_OK != aht21_init( p_self_instance ) )
    {
#ifdef DEBUG
        DEBUG_OUT( "aht21_instance_inst init error\r\n" );
#endif  // DEBUG
        return AHT21_ERRORPARAMETER;
    }

    return AHT21_OK;
}
//******************************** Declaring ********************************//
